Page({
  data: {
    // --- 食堂信息 ---
    canteens: [
      { id: 1, name: '一食堂' },
      { id: 2, name: '二食堂' },
      { id: 3, name: '三食堂' },
      { id: 4, name: '清真食堂' }
    ],
    selectedCanteenId: 1, // 默认选中第一个
    selectedCanteenName: '一食堂',

    // --- AI 拥挤度预测 ---
    loadingCrowd: false,
    crowdStatus: {
      current: [],
      predicted: [],
      predictionTime: '',
      raw: '' // Store raw AI response for debugging or display on parse failure
    },

    // --- AI 个性化推荐 ---
    loadingRecommend: false,
    userPreferences: { // 从本地存储加载
        taste: ['低脂', '偏爱辣味'], // 示例
        allergies: []
    },
    recommendationReason: '', // AI 返回的推荐理由
    recommendations: [], // 推荐菜品列表
    allDishes: [], // 假设一个包含所有菜品的列表，用于筛选

    // --- AI 营养搭配分析 ---
    analyzingNutrition: false,
    selectedDishes: [], // 用户勾选的菜品
    nutritionAnalysisResult: '', // AI 分析结果

    // --- 偏好设置 Modal ---
    showPreferenceModal: false, // 控制弹窗显示
    allTasteOptions: ['不辣', '微辣', '中辣', '重辣', '偏甜', '偏酸', '清淡', '味重', '素食', '低脂'], 
    allAllergyOptions: ['海鲜', '花生', '鸡蛋', '牛奶', '面筋', '香菜'], 
    modalTastePrefs: {}, // 弹窗内临时的口味选择状态
    modalAllergies: {}, // 弹窗内临时的过敏选择状态

    // --- API 相关 (已切换到智谱AI) ---
    useZhipuAI: true, // 是否使用智谱AI而不是OpenRouter
    apiFailedCount: 0 // 记录API调用失败次数，用于自动切换到备用模式
  },

  onLoad: function (options) {
    this.loadUserPreferences();
    this.updateSelectedCanteenName();
    this.fetchAllDishes(); // 先加载菜品基础数据
    this.fetchCrowdStatus(); // 页面加载时获取拥挤度
  },

  onShow: function() {
      // 如果从偏好设置页返回，可能需要重新加载偏好并推荐
      this.loadUserPreferences();
      // 可以考虑只在偏好有变化时重新推荐，或每次onShow都刷新
      this.fetchRecommendations();
  },

  // --- 数据加载与保存 ---
  loadUserPreferences: function() {
    var prefs = wx.getStorageSync('userFoodPreferences');
    if (!prefs) {
      prefs = { taste: [], allergies: [] };
    }
    // 确保默认值是数组
    prefs.taste = Array.isArray(prefs.taste) ? prefs.taste : [];
    prefs.allergies = Array.isArray(prefs.allergies) ? prefs.allergies : [];
    
    var prefsObj = {userPreferences: prefs};
    this.setData(prefsObj);
    console.log("已加载饮食偏好:", this.data.userPreferences);
  },

  saveUserPreferences: function() {
    wx.setStorageSync('userFoodPreferences', this.data.userPreferences);
    console.log("已保存饮食偏好:", this.data.userPreferences);
  },

  // --- 事件处理 ---
  switchCanteen: function(e) {
    var newId = parseInt(e.currentTarget.dataset.id, 10); //确保是数字
    if (newId !== this.data.selectedCanteenId) {
      var idObj = {selectedCanteenId: newId};
      this.setData(idObj);
      this.updateSelectedCanteenName();
      this.fetchCrowdStatus();
      this.fetchRecommendations(); // 切换食堂也重新推荐
    }
  },

  updateSelectedCanteenName: function() {
      var self = this;
      for (var i = 0; i < this.data.canteens.length; i++) {
        var canteen = this.data.canteens[i];
        if (canteen.id === this.data.selectedCanteenId) {
          var nameObj = {selectedCanteenName: canteen.name};
          this.setData(nameObj);
          break;
        }
      }
  },

  // 处理菜品 Checkbox 变化 (使用 checkbox-group 的 bindchange)
  handleCheckboxChange: function(e) {
    var selectedValues = e.detail.value; // value 是选中的 checkbox 的 value 数组
    console.log("选中的值:", selectedValues);
    
    // 创建推荐菜品的副本，更新选中状态
    var recommendations = [];
    for (var i = 0; i < this.data.recommendations.length; i++) {
      var dish = this.data.recommendations[i];
      var dishCopy = JSON.parse(JSON.stringify(dish)); // 创建副本
      
      // 检查dish.id是否在selectedValues中
      var dishIdStr = String(dishCopy.id);
      var isSelected = false;
      for (var v = 0; v < selectedValues.length; v++) {
        if (selectedValues[v] === dishIdStr) {
          isSelected = true;
          break;
        }
      }
      dishCopy.selected = isSelected;
      recommendations.push(dishCopy);
    }
    
    // 过滤出已选中的菜品
    var selectedDishes = [];
    for (var j = 0; j < recommendations.length; j++) {
      if (recommendations[j].selected) {
        selectedDishes.push(recommendations[j]);
      }
    }

    var updateObj = {
      recommendations: recommendations,
      selectedDishes: selectedDishes,
      nutritionAnalysisResult: '' // 清空之前的分析结果
    };
    this.setData(updateObj);
    console.log("已选菜品:", selectedDishes);
  },
  
  // 辅助函数：检查数组是否包含某元素（不再使用此函数，直接在上面进行检查）
  arrayIncludes: function(array, item) {
    for (var i = 0; i < array.length; i++) {
      if (array[i] === item) {
        return true;
      }
    }
    return false;
  },

  gotoPreferenceSettings: function() {
      // 跳转到口味偏好设置页面 (待创建)
      wx.navigateTo({
          url: '/pages/smart_canteen/preference_settings/preference_settings' // 假设页面路径
      });
      // wx.showToast({ title: '跳转偏好设置 (待实现)', icon: 'none' });
  },

  // --- AI 功能 ---

  /**
   * 调用AI API的通用函数
   * @param {Array<object>} messages - 发送给模型的消息数组
   * @param {string} loadingFlag - 控制加载状态的 data 属性名
   * @param {function} [onSuccess] - 成功回调，参数为 AI 响应文本
   * @param {function} [onError] - 失败回调
   * @param {string} [resultField] - 可选，如果需要直接将结果设置到某个字段
   * @param {string} [mockDataType] - 模拟数据类型，用于API调用失败时
   */
  callAIAPI: function(messages, loadingFlag, onSuccess, onError, resultField, mockDataType) {
    if (resultField === undefined) resultField = null;
    if (mockDataType === undefined) mockDataType = 'default';
    
    var dataObj = {};
    dataObj[loadingFlag] = true;
    this.setData(dataObj);
    
    if (resultField) {
        var clearObj = {};
        clearObj[resultField] = '';
        this.setData(clearObj); // 清空旧结果
    }

    // 引入智谱AI模块
    const zhipuAI = require('../../utils/zhipu_ai');
    
    // 使用智谱AI API
    if (this.data.useZhipuAI) {
      var self = this; // 保存this引用
      zhipuAI.callZhipuAPI(messages, {
        model: 'glm-4-air-250414', // 使用较小的模型以降低成本
        fallbackToMock: true, // 开启API调用失败时自动使用模拟数据
        mockType: mockDataType, // 模拟数据类型
        onSuccess: function(aiResponse, fullResponse) {
          console.log('智谱AI响应成功:', aiResponse);
          
          // 如果是模拟数据，显示通知
          if (fullResponse && fullResponse.mock) {
            wx.showToast({
              title: '使用模拟数据返回结果',
              icon: 'none',
              duration: 2000
            });
          } else {
            var resetObj = {apiFailedCount: 0};
            self.setData(resetObj); // 重置失败计数
          }
          
          if (resultField) {
            var resultObj = {};
            resultObj[resultField] = aiResponse;
            self.setData(resultObj);
          }
          
          if (onSuccess) onSuccess(aiResponse);
        },
        onError: function(errorMsg, errorData) {
          console.error('智谱AI响应错误:', errorMsg, errorData);
          
          // 增加失败计数
          var newFailCount = self.data.apiFailedCount + 1;
          var countObj = {apiFailedCount: newFailCount};
          self.setData(countObj);
          
          // 如果连续失败超过3次，自动切换到模拟数据模式
          if (newFailCount >= 3) {
            wx.showToast({
              title: '已自动切换到模拟数据模式',
              icon: 'none',
              duration: 2000
            });
            
            // 使用模拟数据
            var mockResult = zhipuAI.getMockData(mockDataType);
            if (resultField) {
              var mockObj = {};
              mockObj[resultField] = mockResult;
              self.setData(mockObj);
            }
            if (onSuccess) onSuccess(mockResult);
          } else {
            // 显示错误消息
            if (errorMsg.includes('429') || errorMsg.includes('401')) {
              var toastMsg = errorMsg.includes('429') 
                ? '今日API调用次数已超限，使用模拟数据'
                : 'API认证失败，使用模拟数据';
              
              wx.showToast({
                title: toastMsg,
                icon: 'none',
                duration: 3000
              });
              
              // 使用模拟数据
              var mockResult = zhipuAI.getMockData(mockDataType);
              if (resultField) {
                var mockObj = {};
                mockObj[resultField] = mockResult;
                self.setData(mockObj);
              }
              if (onSuccess) onSuccess(mockResult);
            } else {
              // 其他错误
              if (resultField) {
                var errObj = {};
                errObj[resultField] = 'AI服务暂时不可用: ' + errorMsg;
                self.setData(errObj);
              }
              if (onError) onError(errorMsg);
            }
          }
        },
        onComplete: function() {
          var completeObj = {};
          completeObj[loadingFlag] = false;
          self.setData(completeObj);
        }
      }).catch(function(err) {
        console.error('AI API调用异常:', err);
        var errorObj = {};
        errorObj[loadingFlag] = false;
        self.setData(errorObj);
      });
    } else {
      // 使用模拟数据
      var self = this;
      setTimeout(function() {
        var zhipuAI = require('../../utils/zhipu_ai');
        var mockResult = zhipuAI.getMockData(mockDataType);
        
        if (resultField) {
          var resultObj = {};
          resultObj[resultField] = mockResult;
          self.setData(resultObj);
        }
        
        if (onSuccess) onSuccess(mockResult);
        
        var loadingObj = {};
        loadingObj[loadingFlag] = false;
        self.setData(loadingObj);
        
        wx.showToast({
          title: '已使用模拟数据，API调用已关闭',
          icon: 'none'
        });
      }, 1000);
    }
  },

  // 加载所有菜品数据 (应替换为 API 调用或配置文件)
  fetchAllDishes: function() {
       var mockAllDishes = [
            { id: 1, name: '麻婆豆腐', location: '一食堂一楼 | 川味窗口', tags: ['微辣', '素食'], price: 6.0, image: '/images/dishes/mapo_tofu.png' },
            { id: 2, name: '清蒸鲈鱼', location: '一食堂二楼 | 特色蒸菜', tags: ['清淡', '低脂', '推荐'], price: 15.0, image: '/images/dishes/steamed_fish.png' },
            { id: 3, name: '宫保鸡丁', location: '一食堂一楼 | 川味窗口', tags: ['微辣', '家常'], price: 10.0, image: '/images/dishes/gongbao_chicken.png' },
            { id: 4, name: '番茄炒蛋', location: '二食堂一楼 | 家常菜', tags: ['家常', '素食'], price: 5.0, image: '/images/dishes/tomato_egg.png' },
            { id: 5, name: '红烧肉', location: '一食堂二楼 | 红烧系列', tags: ['味重', '下饭'], price: 12.0, image: '/images/dishes/braised_pork.png' },
            { id: 6, name: '水煮牛肉', location: '三食堂 | 川菜特色', tags: ['麻辣', '推荐'], price: 18.0, image: '/images/dishes/boiled_beef.png' },
            { id: 7, name: '手撕包菜', location: '二食堂一楼 | 素菜', tags: ['清淡', '素食'], price: 4.0, image: '/images/dishes/shredded_cabbage.png' },
            { id: 8, name: '酸菜鱼', location: '三食堂 | 特色菜', tags: ['酸辣'], price: 20.0, image: '/images/dishes/sauerkraut_fish.png' },
            { id: 9, name: '红烧牛肉面', location: '一食堂一楼 | 面食窗口', tags: ['面食', '牛肉'], price: 12.0, image: '/images/dishes/beef_noodle.png' },
            { id: 10, name: '鱼香肉丝', location: '一食堂一楼 | 川味窗口', tags: ['微辣', '家常'], price: 8.0, image: '/images/dishes/fish_flavored_pork.png' },
            { id: 11, name: '紫菜蛋花汤', location: '二食堂二楼 | 汤品', tags: ['汤类', '清淡'], price: 4.0, image: '/images/dishes/seaweed_soup.png' },
            { id: 12, name: '清炒时蔬', location: '一食堂一楼 | 素菜窗口', tags: ['素食', '清淡'], price: 5.0, image: '/images/dishes/stir_fried_vegetables.png' },
            { id: 13, name: '回锅肉', location: '一食堂二楼 | 川菜窗口', tags: ['微辣', '肉类'], price: 14.0, image: '/images/dishes/twice_cooked_pork.png' },
            { id: 14, name: '土豆牛肉', location: '二食堂一楼 | 炒菜', tags: ['牛肉', '家常'], price: 16.0, image: '/images/dishes/potato_beef.png' },
            { id: 15, name: '青椒土豆丝', location: '一食堂一楼 | 素菜窗口', tags: ['素食', '微辣'], price: 5.0, image: '/images/dishes/green_pepper_potato.png' },
       ];
       var self = this;
       var dishesObj = {allDishes: mockAllDishes};
       this.setData(dishesObj, function() {
            self.fetchRecommendations(); // 获取基础数据后再进行首次推荐
       });
  },

  // 1. 获取拥挤度状态 (使用 AI)
  fetchCrowdStatus: function() {
    var canteenName = this.data.selectedCanteenName;
    var userPrompt = "请预测一下 " + canteenName + " 主要区域（如一楼窗口、二楼自选区等）当前的排队拥挤情况以及半小时后的预测情况。\n**必须**使用中文回答，格式如下，并明确包含拥挤等级(拥挤/一般/空闲)：\n当前:\n[区域1]: [等级(拥挤/一般/空闲)] [描述]\n[区域2]: [等级(拥挤/一般/空闲)] [描述]\n预测([时间]):\n[区域1]: [等级(拥挤/一般/空闲)] [描述]";

    var statusObj = {
        'crowdStatus.current': [],
        'crowdStatus.predicted': [],
        'crowdStatus.predictionTime': '',
        'crowdStatus.raw': ''
     };
    this.setData(statusObj);

    var self = this;
    this.callAIAPI(
        [{ role: 'user', content: userPrompt }],
        'loadingCrowd',
        function(aiResponse) {
            var rawObj = {'crowdStatus.raw': aiResponse};
            self.setData(rawObj);
            var parsedStatus = self.parseCrowdStatus(aiResponse);
            if (parsedStatus) {
                 var statusObj = { crowdStatus: parsedStatus };
                 self.setData(statusObj);
                 wx.showToast({title:'拥挤度已刷新', icon:'none'});
            } else {
                console.error("Failed to parse crowd status response:", aiResponse);
                 wx.showToast({title:'拥挤度解析失败', icon:'none'});
            }
        },
        function(errorMsg) {
            wx.showToast({title: "获取拥挤度失败", icon:'none'});
            var errObj = { 'crowdStatus.raw': '获取失败，请稍后重试' };
            self.setData(errObj);
        },
        null, // resultField
        'crowd' // mockDataType
    );
  },

  parseCrowdStatus: function(responseText) {
    try {
      var result = {
        current: [],
        predicted: [],
        predictionTime: '半小时后',
        raw: responseText
      };
      
      var lines = responseText.split('\n');
      var trimmedLines = [];
      for (var i = 0; i < lines.length; i++) {
        var trimLine = lines[i].trim();
        if (trimLine) {
          trimmedLines.push(trimLine);
        }
      }
      
      var currentMode = null;
      
      for (var j = 0; j < trimmedLines.length; j++) {
        var line = trimmedLines[j];
        if (line.toLowerCase().includes('当前:') || line.toLowerCase().includes('当前：')) {
          currentMode = 'current';
          continue;
        } else if (line.toLowerCase().includes('预测(') || line.toLowerCase().includes('预测（')) {
          currentMode = 'predicted';
          var timeMatch = line.match(/[预测\(（]([^)）]+)[\)）]/);
          if (timeMatch && timeMatch[1]) {
            result.predictionTime = timeMatch[1];
          }
          continue;
        }
        
        if (!currentMode) continue;
        
        var locationMatch = line.match(/【(.+?)】|［(.+?)］|\[(.+?)\]|\[(.*?)\]|(.+?)[:：]/);
        if (!locationMatch) continue;
        
        var location = '未知区域';
        for (var k = 1; k <= 5; k++) {
          if (locationMatch[k]) {
            location = locationMatch[k];
            break;
          }
        }
        
        var remainingText = line;
        if (locationMatch[0]) {
          remainingText = line.substring(line.indexOf(locationMatch[0]) + locationMatch[0].length).trim();
        }
        
        if (remainingText.startsWith(':') || remainingText.startsWith('：')) {
          remainingText = remainingText.substring(1).trim();
        }
        
        var level = 'medium'; // 默认一般
        
        // 修改等级判断逻辑，适配中文关键词
        if (remainingText.toLowerCase().includes('high') || 
            remainingText.includes('拥挤') || 
            remainingText.includes('较多') || 
            remainingText.includes('人数众多') ||
            remainingText.includes('排队长') ||
            remainingText.includes('满座')) {
          level = 'high'; // 拥挤
        } else if (remainingText.toLowerCase().includes('low') || 
                  remainingText.includes('空闲') || 
                  remainingText.includes('较少') || 
                  remainingText.includes('稀少') ||
                  remainingText.includes('无需排队')) {
          level = 'low'; // 空闲
        }
        
        // 尝试提取描述文本
        var description = remainingText;
        // 移除可能包含的等级标记文本
        description = description.replace(/(high|medium|low|拥挤|一般|空闲)\s*/i, '').trim();
        
        // 如果有方括号中的描述，直接使用
        var descMatch = remainingText.match(/\[(.*?)\]/);
        if (descMatch && descMatch[1]) {
          description = descMatch[1].trim();
        }
        
        var statusItem = {
          location: location,
          level: level,
          description: description
        };
        
        if (currentMode === 'current') {
          result.current.push(statusItem);
        } else if (currentMode === 'predicted') {
          result.predicted.push(statusItem);
        }
      }
      
      return result;
    } catch (error) {
      console.error("解析拥挤度数据时出错:", error);
      return null;
    }
  },

  // 2. 获取推荐菜品 (使用 AI)
  fetchRecommendations: function() {
    var prefs = this.data.userPreferences;
    var tastePref = prefs.taste.join('、') || '无特殊偏好';
    var allergyPref = prefs.allergies.join('、') || '无';
    var canteenName = this.data.selectedCanteenName;

    // 构建更个性化的提示，确保AI真正基于用户偏好进行推荐
    var userPrompt = "基于以下信息为我推荐适合在" + canteenName + "就餐的菜品：\n" +
      "1. 口味偏好：" + tastePref + "\n" +
      "2. 过敏原：" + allergyPref + "\n" +
      "3. 时间：当前是" + new Date().getHours() + "点\n" +
      "4. 目的：希望获得营养均衡且符合我口味的菜品\n\n" +
      "请推荐3-5道具体的菜品，并尽量推荐不同种类的菜品(如荤菜、素菜、汤类等)以保证多样性。\n" +
      "**必须**使用中文回答，**极其简洁**，只需要列出菜品名称即可，用换行符分隔。";

    var recommendObj = {
        recommendations: [],
        selectedDishes: [],
        nutritionAnalysisResult: '',
        recommendationReason: '正在生成...'
    };
    this.setData(recommendObj);

    var self = this;
    this.callAIAPI(
        [{ role: 'user', content: userPrompt }],
        'loadingRecommend',
        function(aiResponse) {
            console.log("Recommendation AI Response:", aiResponse);
            // 处理每一行，确保换行符被正确处理
            var responseText = aiResponse.replace(/\\n/g, '\n');
            
            // 分割并过滤掉空行和过短的行
            var lines = responseText.split('\n');
            var recommendedNames = [];
            for (var i = 0; i < lines.length; i++) {
              // 移除可能的序号前缀，如"1. "或"- "
              var name = lines[i].trim().replace(/^(\d+\.|\-)\s*/, '');
              if (name && name.length > 1) {
                recommendedNames.push(name);
              }
            }
            
            console.log("解析后的菜品名称:", recommendedNames);

            if (recommendedNames.length === 0) {
                 wx.showToast({title:'AI未返回有效推荐', icon:'none'});
                 var reasonObj = { recommendationReason: '未能获取有效推荐，请稍后再试' };
                 self.setData(reasonObj);
                 return;
            }

            // 尝试根据AI的推荐查找预设菜品
            var recommendedDishes = [];
            for (var j = 0; j < self.data.allDishes.length; j++) {
              var dish = self.data.allDishes[j];
              var matched = false;
              
              for (var k = 0; k < recommendedNames.length; k++) {
                var recName = recommendedNames[k];
                // 更宽松的匹配条件
                if (dish.name.includes(recName) || 
                   recName.includes(dish.name) || 
                   self.fuzzyMatch(dish.name, recName)) {
                  matched = true;
                  break;  
                }
              }
              
              if (matched) {
                // 创建一个新对象避免修改原对象
                var dishCopy = JSON.parse(JSON.stringify(dish));
                dishCopy.selected = false;
                recommendedDishes.push(dishCopy);
              }
            }

            // 如果没有匹配到预设菜品或匹配到的菜品少于AI推荐的数量，使用AI直接推荐的菜品
            if (recommendedDishes.length < recommendedNames.length) {
                 console.log("添加AI直接推荐的菜品名称，共" + recommendedNames.length + "个");
                 
                 // 获取已匹配到的菜品名称
                 var matchedNames = [];
                 for (var l = 0; l < recommendedDishes.length; l++) {
                   matchedNames.push(recommendedDishes[l].name);
                 }
                 
                 // 筛选出未匹配到的菜品名称
                 var unmatchedNames = [];
                 for (var m = 0; m < recommendedNames.length; m++) {
                   var name = recommendedNames[m];
                   var isMatched = false;
                   
                   for (var n = 0; n < matchedNames.length; n++) {
                     var matchName = matchedNames[n];
                     if (name.includes(matchName) || 
                        matchName.includes(name) || 
                        self.fuzzyMatch(name, matchName)) {
                       isMatched = true;
                       break;
                     }
                   }
                   
                   if (!isMatched) {
                     unmatchedNames.push(name);
                   }
                 }
                 
                 // 为未匹配的菜品创建新对象
                 var newDishes = [];
                 for (var o = 0; o < unmatchedNames.length; o++) {
                   var name = unmatchedNames[o];
                   var tasteList = [];
                   if (self.data.userPreferences.taste && self.data.userPreferences.taste.length > 0) {
                     for (var p = 0; p < Math.min(2, self.data.userPreferences.taste.length); p++) {
                       tasteList.push(self.data.userPreferences.taste[p]);
                     }
                   }
                   tasteList.push('推荐');
                   
                   var newDish = {
                     id: Date.now() + 1000 + o, // 确保ID唯一
                     name: name,
                     location: self.data.selectedCanteenName + ' | AI推荐',
                     tags: tasteList,
                     selected: false
                   };
                   newDishes.push(newDish);
                 }
                 
                 // 合并已匹配和未匹配的菜品
                 for (var q = 0; q < newDishes.length; q++) {
                   recommendedDishes.push(newDishes[q]);
                 }
            }

            // 不限制菜品数量，显示所有推荐
            var updateObj = {
                recommendations: recommendedDishes,
                recommendationReason: '根据您的口味偏好和当前时间，AI为您推荐了' + recommendedDishes.length + '道菜品'
            };
            self.setData(updateObj);
            wx.showToast({title:'AI推荐已生成，共' + recommendedDishes.length + '个', icon:'none'});
        },
        function(errorMsg) {
            wx.showToast({title:'获取推荐失败', icon:'none'});
            var errObj = { 
              recommendations: [], 
              recommendationReason: '获取推荐失败，请稍后再试' 
            };
            self.setData(errObj);
        },
        null, // resultField
        'recommend' // mockDataType
    );
  },

  // 字符串模糊匹配辅助函数
  fuzzyMatch: function(str1, str2) {
    // 简化的中文模糊匹配
    // 移除空格和标点
    function normalize(s) {
      return s.replace(/[\s.,，。、:：!！?？]/g, '');
    }
    var s1 = normalize(str1);
    var s2 = normalize(str2);
    
    // 查找公共子串
    for (var i = 0; i < s1.length; i++) {
      for (var j = 0; j < s2.length; j++) {
        if (s1[i] === s2[j]) {
          // 找到一个匹配字符，检查是否有连续匹配
          var match = 1;
          var k = 1;
          while (i + k < s1.length && j + k < s2.length && s1[i + k] === s2[j + k]) {
            match++;
            k++;
          }
          // 如果连续匹配2个以上字符，认为是相似的
          if (match >= 2) return true;
        }
      }
    }
    return false;
  },

  // 3. 分析营养搭配 (使用 AI)
  analyzeNutrition: function() {
    if (this.data.selectedDishes.length === 0) return;

    var dishNames = '';
    for (var i = 0; i < this.data.selectedDishes.length; i++) {
      if (i > 0) dishNames += '、';
      dishNames += this.data.selectedDishes[i].name;
    }
    
    var userPrompt = "我选择了以下菜品：" + dishNames + "。请**必须**使用中文，**极其简洁**地分析这顿饭的营养搭配（比如蛋白质、脂肪、碳水、维生素的主要情况），并给出 1-2 条核心改进建议。不要任何解释或多余的话。";

    var resultObj = { nutritionAnalysisResult: '' };
    this.setData(resultObj);

    var self = this;
    this.callAIAPI(
        [{ role: 'user', content: userPrompt }],
        'analyzingNutrition',
        function(aiResponse) {
            console.log("Nutrition Analysis AI Response:", aiResponse);
            var analysisObj = { nutritionAnalysisResult: aiResponse };
            self.setData(analysisObj);
            wx.showToast({title:'营养分析完成', icon:'none'});
        },
        function(errorMsg) {
            wx.showToast({title:"营养分析失败", icon:'none'});
            var errObj = { nutritionAnalysisResult: '分析失败，请稍后再试' };
            self.setData(errObj);
        },
        'nutritionAnalysisResult', // resultField
        'nutrition' // mockDataType
    );
  },

  // 4. 智能换餐 (待实现)
  smartSwap: function() {
      wx.showToast({ title: '智能换餐功能待实现', icon: 'none' });
  },

  // --- 偏好设置 Modal 相关 ---
  showPreferenceModal: function() {
    var currentTaste = this.data.userPreferences.taste || [];
    var currentAllergies = this.data.userPreferences.allergies || [];
    var modalTastePrefs = {};
    
    for (var i = 0; i < this.data.allTasteOptions.length; i++) {
      var option = this.data.allTasteOptions[i];
      var included = false;
      for (var j = 0; j < currentTaste.length; j++) {
        if (currentTaste[j] === option) {
          included = true;
          break;
        }
      }
      modalTastePrefs[option] = included;
    }
    
    var modalAllergies = {};
    for (var k = 0; k < this.data.allAllergyOptions.length; k++) {
      var option = this.data.allAllergyOptions[k];
      var included = false;
      for (var l = 0; l < currentAllergies.length; l++) {
        if (currentAllergies[l] === option) {
          included = true;
          break;
        }
      }
      modalAllergies[option] = included;
    }

    var modalObj = {
      showPreferenceModal: true,
      modalTastePrefs: modalTastePrefs,
      modalAllergies: modalAllergies
    };
    this.setData(modalObj);
  },

  closePreferenceModal: function() {
    this.setData({ showPreferenceModal: false });
  },

  // 处理弹窗内口味 checkbox 变化
  handleModalTasteChange: function(e) {
    var selectedValues = e.detail.value; // ["微辣", "清淡"]
    var modalTastePrefs = {};
    
    for (var i = 0; i < this.data.allTasteOptions.length; i++) {
      var option = this.data.allTasteOptions[i];
      var included = false;
      for (var j = 0; j < selectedValues.length; j++) {
        if (selectedValues[j] === option) {
          included = true;
          break;
        }
      }
      modalTastePrefs[option] = included;
    }
    
    this.setData({ modalTastePrefs: modalTastePrefs });
  },

  // 处理弹窗内过敏 checkbox 变化
  handleModalAllergyChange: function(e) {
    var selectedValues = e.detail.value; // ["海鲜", "花生"]
    var modalAllergies = {};
    
    for (var i = 0; i < this.data.allAllergyOptions.length; i++) {
      var option = this.data.allAllergyOptions[i];
      var included = false;
      for (var j = 0; j < selectedValues.length; j++) {
        if (selectedValues[j] === option) {
          included = true;
          break;
        }
      }
      modalAllergies[option] = included;
    }
    
    this.setData({ modalAllergies: modalAllergies });
  },

  // 保存弹窗中的偏好设置
  savePreferencesFromModal: function() {
    var newTastePrefs = [];
    for (var key in this.data.modalTastePrefs) {
      if (this.data.modalTastePrefs[key]) {
        newTastePrefs.push(key);
      }
    }
    
    var newAllergies = [];
    for (var key in this.data.modalAllergies) {
      if (this.data.modalAllergies[key]) {
        newAllergies.push(key);
      }
    }

    var prefObj = {
      'userPreferences.taste': newTastePrefs,
      'userPreferences.allergies': newAllergies,
      showPreferenceModal: false // 关闭弹窗
    };
    this.setData(prefObj);

    this.saveUserPreferences(); // 保存到本地存储
    this.fetchRecommendations(); // 重新获取推荐
  }
}) 